#pragma once

#include<iostream>
#include<string>
#include<jsoncpp/json/json.h>

class Request
{
public:
    Request():_x(0) ,_y(0),_oper(0)
    {}
    ~Request(){}
    //序列化与反序列化,返回false true 表示处理是否成功
    bool Serialize(std::string*out)
    {
        //使用json
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        //将json 串转换为普通的字符串，使用StyledWriter
        Json::StyledWriter writer;
        *out = writer.write(root);
        if(out->empty()) return false;
        return true;
    }
    bool UnSerialize(const std::string & in)
    {
        Json::Value root;
        Json::Reader reader;
        bool r = reader.parse(in , root);
        if(!r) return false;

        //将数据从Json 串 放入结构中
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();
        return true;
    }

    //提供Get函数
    int X()
    {
        return _x;
    }
    int Y()
    {
        return _y;
    }
    char Oper()
    {
        return _oper;
    }

// private:
    int _x;
    int _y;
    char _oper;
};

class Responce
{
public:
    Responce():_result(0),_code(0)
    {}
    ~Responce(){}
    bool Serialize(std::string* out)
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::StyledWriter writer;
        *out = writer.write(root);
        if(out->empty()) return false;
        return true;

    }

    bool UnSerialize(const std::string& in)
    {
        Json::Value root;
        Json::Reader reader;
        bool r = reader.parse(in, root);
        if(!r) return false;

        _result = root["result"].asInt();
        _code = root["code"].asInt();

        return true;
    }

    //提供Set函数
    void SetResult(int r)
    {
        _result = r;
    }
    void SetCode(int c)
    {
        _code = c;
    }
    //debug
    void Print()
    {
        std::cout << _result << "[" << _code <<"]"<<std::endl;
    }
private:
    int _result;
    int _code;
};

static const std::string sep = "\r\n";

//在报文前面再加上有效载荷长度来确定收到的报文是否完整
class Protocol
{
private:
    static bool DigitalCheck(std::string& str)
    {
        for(int i = 0;i<str.size();i++)
        {
            if(!(str[i] >='0' && str[i]<='9')) return false;
        }
        return true;
    }
public:
    //打包与解包，返回处理过后的字符串
    static std::string Package(const std::string& jsonstr)
    {
        if(jsonstr.empty()) return std::string();
        std::string send_str = std::to_string(jsonstr.size());
        send_str += sep;
        send_str += jsonstr;
        send_str += sep;

        return send_str;
    }    

    //解包 -> 返回jsonstr
    //返回值为0，继续读取;-1：协议有误，进程终止；其他：成功
    static int Unpack(std::string &origin_str , std::string*jsonstr)//
    {
        //找到分隔符，得到json串的长度，如果小于就继续去读
        if(!jsonstr) return 0;

        //在origin_str 中查找分隔符
        auto pos = origin_str.find(sep);
        if(pos == std::string::npos) return 0;
        //获取json 串的长度信息
        std::string len_str = origin_str.substr(0 , pos);
        //判断len_str 中是否含有非数字字符
        if(!DigitalCheck(len_str)) return -1;
        int digit_len = std::stoi(len_str);
        //推导整个报文的长度
        int target_len = len_str.size() + sep.size()*2 + digit_len;
        //判断 origin_str 中的报文是否完整
        if(origin_str.size() < target_len) return 0; 

        // origin_str 中至少有一个完整的报文
        *jsonstr += origin_str.substr(pos+sep.size() , digit_len);
        origin_str.erase(0, target_len);
        return jsonstr->size();
    }
};